home *** CD-ROM | disk | FTP | other *** search
/ 17 Bit Software 6: Level 6 / 17 Bit - Level 6 (1998)(Epic Marketing)[!].iso / quartz / q1082.dms / q1082.adf / src.lzh / Fig / geom.c < prev    next >
C/C++ Source or Header  |  1991-07-18  |  5KB  |  213 lines

  1. /* 
  2.  *    FIG : Facility for Interactive Generation of figures
  3.  *
  4.  *    Copyright (c) 1988 by Supoj Sutanthavibul (supoj@sally.UTEXAS.EDU)
  5.  *    March 1988.
  6.  *
  7.  *    %W%    %G%
  8. */
  9. #include "fig.h"
  10. #include "object.h"
  11.  
  12. #ifndef PI
  13. #define            PI        3.14159
  14. #endif
  15. #define             round(x)    ((int)((x) + .5))
  16.  
  17. /*
  18. Input arguments :
  19.     (x1,y1)(x2,y2) : the vector
  20.     direction : direction of the normal vector to (x1,y1)(x2,y2)
  21. Output arguments :
  22.     (*x,*y)(x2,y2) : a normal vector.
  23. Return value : none
  24. */
  25.  
  26. compute_normal(x1, y1, x2, y2, direction, x, y)
  27. float    x1, y1;
  28. int    x2, y2,    direction, *x, *y;
  29. {
  30.     if (direction) { /* counter clockwise  */
  31.         *x = round(x2 - (y2 - y1));
  32.         *y = round(y2 - (x1 - x2));
  33.         }
  34.     else {
  35.         *x = round(x2 + (y2 - y1));
  36.         *y = round(y2 + (x1 - x2));
  37.         }
  38.     }
  39.  
  40. /*
  41. Input arguments:
  42.     (x1,y1)(x2,y2) : the vector
  43.     (xp,yp) : the point
  44.     d : tolerance (max. allowable distance from the point to the vector)
  45.     dd : d * d
  46. Output arguments:
  47.     (*px,*py) : a point on the vector which is not far from (xp,yp)
  48.         by more than d. Normally the vector (*px,*py)(xp,yp)
  49.         is normal to vector (x1,y1)(x2,y2) except when (xp,yp)
  50.         is within d from (x1,y1) or (x2,y2), in which cases,
  51.         (*px,*py) = (x1,y1) or (x2,y2) respectively. 
  52. Return value :
  53.     0 : No point on the vector is within d from (xp, yp)
  54.     1 : (*px, *py) is such a point.
  55. */
  56.  
  57. close_to_vector(x1, y1, x2, y2, xp, yp, d, dd, px, py)
  58. int     x1, y1, x2, y2, xp, yp, d;
  59. float     dd;
  60. int    *px, *py;
  61. {
  62.     int    xmin, ymin, xmax, ymax;
  63.     float    x, y, slope, D2, dx, dy;
  64.  
  65.     if (abs(xp - x1) <= d && abs(yp - y1) <= d) {
  66.         *px = x1;  *py = y1;
  67.         return(1);
  68.         }
  69.     if (abs(xp - x2) <= d && abs(yp - y2) <= d) {
  70.         *px = x2;  *py = y2;
  71.         return(1);
  72.         }
  73.  
  74.     if (x1 < x2) {
  75.         xmin = x1 - d; xmax = x2 + d;
  76.         }
  77.     else {
  78.         xmin = x2 - d; xmax = x1 + d;
  79.         }
  80.     if (xp < xmin || xmax < xp) return(0);
  81.  
  82.     if (y1 < y2) {
  83.         ymin = y1 - d; ymax = y2 + d;
  84.         }
  85.     else {
  86.         ymin = y2 - d; ymax = y1 + d;
  87.         }
  88.     if (yp < ymin || ymax < yp) return(0);
  89.  
  90.     if (x2 == x1) {
  91.         x = x1; y = yp;
  92.         }
  93.     else if (y1 == y2) {  
  94.         x = xp;
  95.         y = y1;
  96.         }
  97.     else {
  98.         slope = ((float) (x2 - x1)) / ((float) (y2 - y1));
  99.         y = (slope * (xp - x1 + slope * y1) + yp) / (1 + slope * slope);
  100.         x = ((float) x1) + slope * (y - y1);
  101.         }
  102.     dx = ((float) xp) - x;
  103.     dy = ((float) yp) - y;
  104.     D2 = dx * dx + dy * dy;
  105.     if (D2 < dd) {
  106.         *px = (int)(x + .5); *py = (int)(y +.5);
  107.         return(1);
  108.         }
  109.     return(0);
  110.     }
  111.  
  112. /*
  113. Input arguments :
  114.     p1, p2, p3 : 3 points on the arc
  115. Output arguments :
  116.     (*x,*y) : Center of the arc
  117. Return value :
  118.     0 : if p1, p2, p3 are co-linear.
  119.     1 : if they are not.
  120. */
  121.  
  122. int
  123. compute_arccenter(p1, p2, p3, x, y)
  124. F_pos    p1, p2, p3;
  125. float    *x, *y;
  126. {
  127.     float    s12, s13, len1, len2, len3, dx12, dy12, dx13, dy13;
  128.  
  129.     dx12 = p1.x - p2.x;  dy12 = p1.y - p2.y;
  130.     dx13 = p1.x - p3.x;  dy13 = p1.y - p3.y;
  131.     s12 = asin((double)(dy12 / sqrt((double)(dx12*dx12 + dy12*dy12))));
  132.     s13 = asin((double)(dy13 / sqrt((double)(dx13*dx13 + dy13*dy13))));
  133.     if (fabs(s12 - s13) < .01) return(0);
  134.     
  135.     len1 = p1.x * p1.x + p1.y * p1.y;
  136.     len2 = p2.x * p2.x + p2.y * p2.y;
  137.     len3 = p3.x * p3.x + p3.y * p3.y;
  138.     *y = (dx12 * (len3 - len1) - dx13 * (len2 - len1)) /
  139.         (2 * (dx13 * dy12 - dx12 * dy13));
  140.     if (dx13 != 0) 
  141.         *x = (len3 + 2 * (*y) * dy13 - len1) / (2 * (-dx13));
  142.     else
  143.         *x = (len2 + 2 * (*y) * dy12 - len1) / (2 * (-dx12));
  144.     return(1);
  145.     }
  146.  
  147. /*
  148. Compute_angle
  149. Input arguments :
  150.     (dx,dy) : the vector (0,0)(dx,dy)
  151. Output arguments : none
  152. Return value : the angle of the vector in the range [0, 2PI)
  153. */
  154.  
  155. float
  156. compute_angle(dx, dy)  /*  compute the angle between 0 to 2PI  */
  157. float    dx, dy;
  158. {
  159.     float    alpha;
  160.  
  161.     if (dx == 0) {
  162.         if (dy > 0)
  163.         alpha = PI / 2;
  164.         else
  165.         alpha = 3 * PI / 2;
  166.         }
  167.     else if (dy == 0) {
  168.         if (dx > 0) 
  169.         alpha = 0;
  170.         else
  171.         alpha = PI;
  172.         }
  173.     else {
  174.         alpha = atan((double)(dy / dx)); /* range = -PI/2 to PI/2 */
  175.         if (dx < 0) alpha += PI;
  176.         else if (dy < 0) alpha += 2 * PI;
  177.         }
  178.     return(alpha);
  179.     }
  180.  
  181. /*
  182. Input arguments :
  183.     p1, p2, p3 : 3 points of an arc with p1 the first and p3 the last.
  184. Output arguments : none
  185. Return value :
  186.     0 : if the arc passes p1, p2 and p3 (in that order) in
  187.         clockwise direction
  188.     1 : if direction is counterclockwise
  189. */
  190.  
  191. int
  192. compute_direction(p1, p2, p3)
  193. F_pos    p1, p2, p3;
  194. {
  195.     float        diff, dx, dy, alpha, theta;
  196.  
  197.     dx = p2.x - p1.x;
  198.     dy = p1.y - p2.y;    /* because origin of the screen is on 
  199.                     the upper left corner */
  200.     
  201.     alpha = compute_angle(dx, dy);
  202.  
  203.     dx = p3.x - p2.x;
  204.     dy = p2.y - p3.y;
  205.     theta = compute_angle(dx, dy);
  206.     
  207.     diff = theta - alpha;
  208.     if ((0 < diff && diff < PI) || diff < -PI) {
  209.         return(1);            /* counterclockwise */
  210.         }
  211.     return(0);            /* clockwise */
  212.     }
  213.